module builtin

// misc fixes
__global (vnil = voidptr(0))
// hotfix V fn C.func() void problem
pub type Void = int


///////////// Any type
// just as voidptr
pub fn (this charptr) str() string {
	that := voidptr(this)
	return that.str()
}
pub fn (this size_t) str() string {
    return int(this).str()
}

pub struct Mival {
    pub mut:
    data voidptr
    typ int
}
pub fn (v int) tomiv() Mival {
    return Mival{}
}

//any_int | any_float
pub type Any = bool |
    int | byte | i16 | u16 | u32 | i64 | u64 |
    f32 | f64 | string |
    []int |
    []i64 |
    []f64 |
    []voidptr|
    []byteptr|
    []charptr|
    []string |
    []Any |
    map[string]string|
    map[voidptr]string|
    map[int]string|
    size_t |
    []size_t |
	voidptr | byteptr | charptr

pub fn sprintaddd(args ...Any) string {
    mut buf := ""
    return buf
}

pub fn sprinta(args ...Any) string {
	mut buf := ""
	//buf = buf.repeat
    for idx, arg in args {
        match arg {
            bool { buf = arg.str() }
            int { buf += arg.str() }
            u32 { buf += arg.str() }
            i64 { buf += arg.str() }
            u64 { buf += arg.str() }
            voidptr { buf += "$arg" }
            string { buf += arg }
            // array_string { buf += arg }
            f32 { buf += arg.str() }
            f64 { buf += arg.str() }
            else {
                tystr := typeof(arg)
                valstr := arg.str()
                valstr2 := valstr[4..valstr.len-1]
                match typeof(arg) {
                    "[]string" { buf = buf + tystr + valstr2 }
                    else{
                        buf = buf + tystr + valstr
                    }
                }
            }
        }
        if idx != args.len -1{
            buf += ' '
        }
    }
    return buf

}


pub fn sprinta2(args ...Any) string {
    mut cap := 128
    mut line := byteptr(vcalloc(cap))

    mut pos := 0
    mut addn := 0
	//buf = buf.repeat
    mut buf := ""
    for idx, arg in args {
        match arg {
            bool { buf = arg.str() }
            int {
                // buf = arg.str()
                addn = C.sprintf(line+pos, "%d", arg)
                pos += addn
            }
            u32 { buf = arg.str() }
            i64 { buf = arg.str() }
            u64 { buf = arg.str() }
            voidptr { buf = "$arg" }
            string {
                // buf = arg
                //addn = C.sprintf(line+pos, "%s", arg.str)
                C.memcpy(line+pos, arg.str, arg.len)
                pos += arg.len
            }
            f32 { buf = arg.str() }
            f64 {
                // buf = arg.str()
                addn = C.sprintf(line+pos, "%f", arg)
                pos += addn
            }
            // array_string { buf = arg }
            else {
                // tystr := typeof(arg)
                // valstr := arg.str()
                // valstr2 := valstr[4..valstr.len-1]
                // match typeof(arg) {
                   // "[]string" { buf = tystr + valstr2 }
                    //else{
                      //  buf = tystr + valstr
                //}
                //}
                //buf = arg.str()
                buf  = arg.str()
            }
        }

        if pos+buf.len > cap {
            newlen := if pos+buf.len > (cap*2) { pos+buf.len } else { cap*2 }
            line = v_realloc(line, newlen)
        }
        //C.memcpy(line+pos, buf.str, buf.len)
        //for i := 0; i < buf.len ;i++{
        //    line[pos+i] = buf.str[i]
        //}
        //pos += buf.len
        if idx != args.len -1{
            //buf += ' '
            line[pos] = ` `
            pos ++
        }
    }
    res := tos(line, pos)
    return res
}

pub fn printa(args ...Any) {
	println(sprinta(args...))
}

//////////////////



pub union AnyVal {
    pub mut:
    int_val int
    str_val string
    voidptr_val voidptr
    struct_val voidptr
    f32_val f32
    f64_val f64
    i64_val i64
    u64_val u64
    usz_val size_t
    arr_val array
    map_val map
}
pub struct Vany {
    pub mut:
    val AnyVal
    ityp int
    typ voidptr
    typ2 int
    size int
}

pub fn (xv Vany) toa() Vany {
    return xv
}

pub fn (xv any_int) toa() Vany {
    mut val := AnyVal{}
    val.int_val = xv
    return Vany{val:val, ityp: tkint, size: int(sizeof(xv))}
}
pub fn (xv any_float) toa() Vany {
    return Vany{}
}
pub fn (xv string) toa() Vany {
    // mut val := AnyVal{}
    // val.int_val = xv
    return Vany{ ityp: tkint, size: int(sizeof(xv))}
}
pub fn (xv voidptr) toa() Vany {
    return Vany{}
}

////////////////// export new array
pub fn pnew_array(mylen int, cap int, elm_size int) array {
    return __new_array(mylen, cap, elm_size)
}

pub fn (a array) pget(i int) voidptr {
    return a.get(i)
}
pub fn (mut a array) pset(i int, val voidptr) {
    a.set(i, val)
}

////////////////// type info
// from indent_Any_str
pub const (
    tkbool = 16
    tkint = 7
    tki16 = 9
    tku16 = 10
    tku32 = 11
    tki64 = 8
    tku64 = 12
    tkf32 = 13
    tkf64 = 14
    tkstring = 18
    tkarrint = 30
    tkarri64 = 54
    tkarrf64 = 55
    tkarrvptr = 32
    tkarrbptr = 41
    tkarrcptr = 39
    tkarrstr  = 28
    tkarrany = 57
    tkmapstrstr = 58
    tkmapvptrstr = 59
    tkmapintstr = 60
    tksizet = 24
    tkarrsizet = 61
    tkvoidptr = 2
    tkbyteptr = 3
    tkcharptr = 4
)

////////////////// addr2line


